<?php
/**
 * @Author: laoweizhen <1149243551@qq.com>,
 * @Date: 2022/10/07 10:10,
 * @LastEditTime: 2022/10/07 10:10
 */
declare(strict_types=1);

namespace Zhen\HyperfKit\Exception\Handler;

use Hyperf\Di\Annotation\Inject;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\Logger\LoggerFactory;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use Throwable;
use Zhen\HyperfKit\Constants\ResponseCode;
use Zhen\HyperfKit\CoreResponse;
use Zhen\HyperfKit\Event\ExceptionEvent;
use Zhen\HyperfKit\Exception\CoreException;

class AppExceptionHandler extends ExceptionHandler
{
    private LoggerInterface $logger;

    /**
     * 事件调度器
     * @var EventDispatcherInterface
     */
    #[Inject]
    protected EventDispatcherInterface $evDispatcher;

    public function __construct()
    {
        $this->logger = container()->get(LoggerFactory::class)->get('exception');
    }

    public function handle(Throwable $throwable, ResponseInterface $response)
    {
        $coreResponse = make(CoreResponse::class);

        // 测试环境直接返回错误信息
        if (config('app_env') == 'dev' || config('app_debug') === true) {
            return $coreResponse->debug($throwable);
        }

        // 自定义错误异常：判断是否返回错误信息响应
        if ($throwable instanceof CoreException && $throwable->responseErrInfo) {
            return $coreResponse->error($throwable->getMessage(), $throwable->getCode());
        }

//        $this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
//        $this->logger->error($throwable->getTraceAsString());
        $this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
        
        $this->evDispatcher->dispatch(new ExceptionEvent($throwable));

        return $coreResponse->error();
    }

    public function isValid(Throwable $throwable): bool
    {
        return true;
    }
}